#include "stm32f10x.h"

// 红绿灯和蜂鸣器的GPIO引脚
#define RED_LED_PIN    GPIO_Pin_0
#define YELLOW_LED_PIN GPIO_Pin_1
#define GREEN_LED_PIN  GPIO_Pin_2
#define BUZZER_PIN     GPIO_Pin_3
#define LED_PORT       GPIOA
#define BUZZER_PORT    GPIOA

// 报警按键引脚
#define ALARM_TRIGGER_PIN GPIO_Pin_4
#define ALARM_TRIGGER_PORT GPIOB

uint16_t currentState=0;	//初始状态
uint16_t stateCounter = 0;// 状态计数器
uint8_t alarmFlag = 1; //报警标识


// 初始化GPIO
void GPIO_Configuration(void) {
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能GPIOA和GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = RED_LED_PIN | YELLOW_LED_PIN | GREEN_LED_PIN | BUZZER_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_PORT, &GPIO_InitStructure);

    // 配置触发报警
    GPIO_InitStructure.GPIO_Pin = ALARM_TRIGGER_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(ALARM_TRIGGER_PORT, &GPIO_InitStructure);
}

// 初始化EXTI中断
void EXTI_Configuration(void) {
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能AFIO时钟，用于连接GPIO到EXTI
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    // 将按键引脚连接到EXTI线
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource4);

    // 配置EXTI线
    EXTI_InitStructure.EXTI_Line = EXTI_Line4;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    // 配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// 定时器配置
void TIM_Configuration(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 定时器基本配置
    TIM_TimeBaseStructure.TIM_Period = 9999; 
    TIM_TimeBaseStructure.TIM_Prescaler = 7199; 
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    // 使能TIM2更新中断
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    // 配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能TIM2
    TIM_Cmd(TIM2, ENABLE);
}

// TIM2中断服务函数，控制红绿灯状态切换
void TIM2_IRQHandler(void) {
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) 
		{
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        if (alarmFlag==0) 
			{
            stateCounter++;

            switch (currentState) {
                case 0:
                    if (stateCounter >= 5) { 
                        currentState = 1;
                        stateCounter = 0;
                        GPIO_ResetBits(LED_PORT, GREEN_LED_PIN);
                        GPIO_SetBits(LED_PORT, YELLOW_LED_PIN);
                    }
                    break;
                case 1:
                    if (stateCounter >= 2) { 
                        currentState =2;
                        stateCounter = 0;
                        GPIO_ResetBits(LED_PORT, YELLOW_LED_PIN);
                        GPIO_SetBits(LED_PORT, RED_LED_PIN);
                    }
                    break;
                case 2:
                    if (stateCounter >= 5) { 
                        currentState = 0;
                        stateCounter = 0;
                        GPIO_ResetBits(LED_PORT, RED_LED_PIN);
                        GPIO_SetBits(LED_PORT, GREEN_LED_PIN);
                    }
                    break;
            }
        }
    }
}

// EXTI4中断服务函数，触发或解除报警
void EXTI4_IRQHandler(void) {
    if (EXTI_GetITStatus(EXTI_Line4) != RESET) {
        if (alarmFlag==0) {
            alarmFlag = 1;
            GPIO_ResetBits(LED_PORT, GREEN_LED_PIN | YELLOW_LED_PIN);
            GPIO_SetBits(LED_PORT, RED_LED_PIN);
            GPIO_ResetBits(BUZZER_PORT, BUZZER_PIN);            // 开启蜂鸣器            
        } else {
			alarmFlag = 0;		// 解除报警标识判断
            currentState=0;
            GPIO_SetBits(BUZZER_PORT, BUZZER_PIN);            // 关闭蜂鸣器
        }

        // 清除中断标志
        EXTI_ClearITPendingBit(EXTI_Line4);
    }
}